﻿using Artech.Common;
using Artech.Common.Properties;
using Microsoft.Practices.Unity.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Artech.Core
{
    /// <summary>
    /// This class is used to create a scope based on the given <see cref="DependentContext"/>.
    /// </summary>
    public class ApplicationContextScope: IDisposable
    {
        /// <summary>
        /// Gets the <see cref="DependentContext"/> by which the <see cref="ApplicationContextScope"/> is created.
        /// </summary>
        /// <value>
        /// The <see cref="DependentContext"/>.
        /// </value>
        public DependentContext DependentContext { get; private set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="ApplicationContextScope"/> class.
        /// </summary>
        /// <param name="dependentContext">The dependent context.</param>
        /// <exception cref="System.InvalidOperationException">The <see cref="InvalidOperationException"/> is thrown if current thread is the one in which the <see cref="DependentContext"/> is created.</exception>
        public ApplicationContextScope(DependentContext dependentContext)
        {
            Guard.ArgumentNotNull(dependentContext, "dependentContext");
            if (object.ReferenceEquals(dependentContext.Thread, Thread.CurrentThread))
            {
                throw new InvalidOperationException(ResourceUtility.Format(CoreResources.ExceptionNotSameThread));
            }
            this.DependentContext = dependentContext;
            ApplicationContext.Current.Provider.SetContextItems(dependentContext.Items);
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            this.DependentContext.Items.Clear();
        }
    }
}
